#include "pwext.hpp"
#include <stdio.h>
#include <stdlib.h>

#ifndef EX05_NESTED
#include "ex05fc.cpp"

// copy of ex05ff
template <typename target>
class scopegrab
{
public:
	scopegrab(weakref *ref, target *&result) : ref_(ref)
	{
		result = (target *)ref->grab();
		grabbed_ = true;
	}
	~scopegrab()
	{
		if (grabbed_)
			ref_->release();
	}
	void release()
	{
		if (grabbed_)
			ref_->release();
		grabbed_ = false;
	}
	target *regrab()
	{
		if (grabbed_)
			ref_->release();
		grabbed_ = true;
		return (target *)ref_->grab();
	}
protected:
	weakref *ref_;
	bool grabbed_;
private: // prevent the default and copy constructors and assignments
	scopegrab();
	scopegrab(const scopegrab &);
	void operator=(const scopegrab &);
};
#endif // EX05_NESTED

// [[ex05fg]]
// DEBUG descr The scoped object for temporary release and re-grabbing of the weak references.
template <typename target>
class scopeungrab
{
public:
	scopeungrab(scopegrab<target> &grab, 
			target *&result) : 
		grab_(grab), result_(result)
	{
		grab_.release();
		result_ = 0;
	}
	~scopeungrab()
	{
		result_ = grab_.regrab();
	}
protected:
	scopegrab<target> &grab_;
	target *&result_;
private: 
	// prevent the default and copy constructors and
	// assignments
	scopeungrab();
	scopeungrab(const scopeungrab &);
	void operator=(const scopeungrab &);
};
// END

#ifndef EX05_NESTED
// DEBUG from
class mytarget : public reftarget
{
public:
	mytarget() :
		reftarget(this)
	{ }

	~mytarget()
	{
		invalidate();
	}
};

int main()
{
	mytarget *t = new mytarget;
	weakref *r = t->newweakref();
	{
		mytarget *tt;
		scopegrab<mytarget> scope(r, tt);
		if (tt) {
			fprintf(stderr, "target is still valid\n");
		}
		{
			scopeungrab<mytarget> unscope(scope, tt);
			delete t;
		}
		if (!tt) {
			fprintf(stderr, "target is not valid any more\n");
		}
	}
	return 0;
}

/* Sample result:
target is still valid
target is not valid any more
*/
#endif // EX05_NESTED
